﻿using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Collections;
using System.Runtime.CompilerServices;

#region Copyright (C) 2010 Null Studio
/*
 * Author:Null hetaoos@gmail.com
 * Blog: http://blog.hetaoos.com
 * Copyright (C) 2010 Null Studio
 * 
 * 
 * PACMaker is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * PACMaker is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PACMaker. If not, see <http://www.gnu.org/licenses/>.
 */
#endregion

namespace com.hetaoos.PacMaker.Utils
{

    [Serializable]
    public abstract class XmlSerializerBase<TClass>
        where TClass : class
    {

        /// <summary>
        /// 将该类转换为 XML 文本
        /// </summary>
        /// <returns></returns>
        public string ToXmlString()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer serializer = GetXmlSerializer();
                try
                {
                    serializer.Serialize(ms, this);
                    ms.Close();
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
                catch (Exception ex)
                {
                    Debug.Print(ex.ToString());
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// 保存当前对象到文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public bool WriteObjectToFile(string filePath)
        {
            try
            {
                File.WriteAllText(filePath, ToXmlString());
                return true;
            }
            catch (Exception exc)
            {
                Debug.Print(exc.ToString());
                return false;
            }
        }

        /// <summary>
        /// 从 XML 文件中还原对象
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object ReadObjectFromFile(string filePath, Type type)
        {
            try
            {
                return FromXmlString(File.ReadAllText(filePath), type);
            }
            catch (Exception exc)
            {
                Debug.Print(exc.ToString());
                return null;
            }
        }

        /// <summary>
        /// 从 XML 字符串中还原对象
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static TClass FromXmlString(string xmlString)
        {
            return FromXmlString(xmlString, typeof(TClass)) as TClass;
        }

        /// <summary>
        /// 将对象转换为 XML 字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToXmlString(TClass obj)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer serializer = GetXmlSerializer();
                try
                {
                    serializer.Serialize(ms, obj);
                    ms.Close();
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
                catch (Exception ex)
                {
                    Debug.Print(ex.ToString());
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// 保存对象到文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool WriteObjectToFile(TClass obj, string filePath)
        {
            try
            {
                File.WriteAllText(filePath, ToXmlString(obj));
                return true;
            }
            catch (Exception exc)
            {
                Debug.Print(exc.ToString());
                return false;
            }
        }
        /// <summary>
        /// 从 XML 文件中还原对象
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static TClass ReadObjectFromFile(string fileName)
        {
            return ReadObjectFromFile(fileName, typeof(TClass)) as TClass;
        }


        /// <summary>
        /// 从 XML 字符串中还原对象
        /// </summary>
        /// <param name="xmlString"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object FromXmlString(string xmlString, Type type)
        {
            if (string.IsNullOrEmpty(xmlString))
            {
                return null;
            }
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
            {
                XmlSerializer serializer = GetXmlSerializer(type);
                try
                {
                    return serializer.Deserialize(stream);
                }
                catch
                {
                    return null;
                }
            }

        }

        /// <summary>
        /// 设置默认值
        /// </summary>
        public virtual void SetDefault()
        {
        }



        private static Hashtable XmlSerializerCache = new Hashtable();
        /// <summary>
        /// 序列化转换器缓存，避免重复创建
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static XmlSerializer GetXmlSerializer(Type type)
        {
            lock (XmlSerializerCache)
            {
                XmlSerializer serializer = XmlSerializerCache[type] as XmlSerializer;
                if (serializer == null)
                {
                    serializer = new XmlSerializer(type);
                    XmlSerializerCache[type] = serializer;
                }
                return serializer;
            }
        }

        /// <summary>
        /// 获取当前类的序列话器
        /// </summary>
        /// <returns></returns>
        public static XmlSerializer GetXmlSerializer()
        {
            return GetXmlSerializer(typeof(TClass));
        }
    }

    public static class XmlSerializerEx
    {
        /// <summary>
        /// 将对象转换为 XML 字符串
        /// </summary>
        /// <typeparam name="TClass"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static string ToXmlString<TClass>(this TClass t)
            where TClass : class
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer();
                try
                {
                    serializer.Serialize(ms, t);
                    ms.Close();
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
                catch (Exception ex)
                {
                    Debug.Print(ex.ToString());
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// 将 XML 字符串转换为对象
        /// </summary>
        /// <typeparam name="TClass"></typeparam>
        /// <param name="t"></param>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static TClass FromXmlString<TClass>(this TClass t, string xmlString)
            where TClass : class
        {
            if (string.IsNullOrEmpty(xmlString))
            {
                return null;
            }
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
            {
                XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer();
                try
                {
                    return serializer.Deserialize(stream) as TClass;
                }
                catch
                {
                    return null;
                }
            }
        }
    }
}
